﻿
using System.Net.Sockets;
using System.Net;
using System;
using System.Threading;
using ZDK.Infra.Services;
using ZDK.Infra.Types;
using System.Collections;
using System.Collections.Generic;

namespace ZDK.Utilities
{
    public class TcpServer
    {
        readonly IMyLog _log;

        #region 数据成员

        private Thread _listenThread;
        private bool _serverStart;
        public static SortedList _clients = new SortedList();
        private Socket _listenSocket;
        public Dictionary<string, bool> _socketSyncStatusDict = new Dictionary<string, bool>();
        public DelegateMsgWithParam OnConnect;
        //public DelegateMsg OnSend;
        public DelegateMsgWithParam OnReceive;
        public DelegateMsg OnServerDown;
        //public DelegateMsg OnErr;

        #endregion

        #region 构造
        public TcpServer()
        {

        }

        public TcpServer(IMyLog log, int listenPort, int maxClient)
        {
            _log = log;
            //__ENCList.Add(new WeakReference(this));
            _listenThread = null;
            _serverStart = false;
            try
            {
                string hostName = Dns.GetHostName();
                IPEndPoint localEP = new IPEndPoint(IPAddress.Any, listenPort);
                _listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _listenSocket.Bind(localEP);
                _listenSocket.Listen(maxClient);
                _listenSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.AcceptConnection, 1);
            }
            catch (Exception ex)
            {
                _log.Error($"服务端构造异常：{ex.Message}");
            }
        }
        #endregion

        #region StartServer 启动服务
        public void StartServer()
        {
            _serverStart = true;
            try
            {
                _listenThread = new Thread(ListenClient);
                _listenThread.Name = "监听线程";
                _listenThread.Start();

                _log.Info($"服务端开始监听……");
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[StartServer]异常：{ex.Message}");
                if (_listenSocket != null && _listenSocket.Connected)
                {
                    _listenSocket.Close();
                }
            }
        }

        private void ListenClient()
        {
            while (_serverStart)
            {
                try
                {
                    if (_listenSocket != null)
                    {
                        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        socket = _listenSocket.Accept();

                        if (socket != null)
                        {
                            socket.SendTimeout = 5000;
                            socket.ReceiveTimeout = 5000;
                            socket.NoDelay = true;

                            IPEndPoint ipEndPoint = (IPEndPoint)socket.RemoteEndPoint;
                            string key = ipEndPoint.Address.ToString() + ":" + ipEndPoint.Port;
                            _clients.Add(key, socket);
                            OnConnect(key, socket);
                            _socketSyncStatusDict.Add(key, true);

                            TcpClient client = new TcpClient(_log, _listenSocket, socket, this);
                            //clientCommunication.Exception += WriteErrorEvent_ClientCommunication;
                            Thread thread = new Thread(client.ClientThreadProc);
                            thread.Name = $"client:{key}通讯线程";
                            thread.Start();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _log.Error($"服务端[ListenClient]异常：{ex.Message}");
                }
            }
        }
        #endregion

        #region Close 关闭服务端
        public void Close()
        {
            try
            {
                _serverStart = false;
                //Thread.Sleep(5);
                _listenSocket.Close();
                _listenThread.Abort(); //卡死
                _listenSocket = null;
                _listenThread = null;
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[Close]异常：{ex.Message}");
            }
        }
        #endregion

        #region CloseClient 手动关闭客户端
        public Socket GetClientSocket(string ip, int port)
        {
            string key = ip + ":" + port;
            try
            {
                return (Socket)_clients[key];
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[GetClientSocket]异常：{ex.Message}");
                return null;
            }
        }
        public void CloseClient(string ip, int port)
        {
            Socket s = GetClientSocket(ip, port);
            if (s != null)
            {
                s.Close();
                GetClientClose(ip, port);
            }
        }
        #endregion

        #region GetClientClose 客户端主动关闭
        public void GetClientClose(string ip, int port)
        {
            string key = ip + ":" + port;
            _log.Warn($"客户端[{key}已断开连接！]");

            try
            {
                if (_clients.ContainsKey(key))
                {
                    _log.Warn($"客户端:{key}关闭连接");
                    object syncRoot = _clients.SyncRoot;
                    //ObjectFlowControl.CheckForSyncLockOnValueType(syncRoot);
                    Monitor.Enter(syncRoot);
                    try
                    {
                        _clients.Remove(key);
                    }
                    finally
                    {
                        Monitor.Exit(syncRoot);
                    }
                }
                //ClientCloseEvent?.Invoke(IP, Port);
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[GetClientClose]异常：{ex.Message}");
            }
        }
        #endregion

        #region SendData 发送数据
        public bool SendData(string clientKey, byte[] write_data)
        {
            //Discarded unreachable code: IL_002e, IL_0041, IL_0048
            try
            {
                if (_clients.Count == 0)
                {
                    _log.Warn("无法发送数据，没有连接的客户端！");
                    return false;
                }
                if(write_data == null || write_data.Length == 0)
                {
                    _log.Warn("数据为空！");
                    return false;
                }
                Socket socket = (Socket)_clients[clientKey];
                socket.Send(write_data, write_data.Length, SocketFlags.None);

                return true;
            }
            catch (SocketException e)
            {
                if (e.ErrorCode == 10053)
                {
                    OnServerDown(clientKey);
                }
                else
                {
                    _log.Error($"服务端[SendData]异常：{e.Message}");
                }
                return false;
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[SendData]异常：{ex.Message}");
                return false;
            }
        }
        #endregion

        #region SendFile 发送文件
        public bool SendFile(string clientKey, string value)
        {
            //Discarded unreachable code: IL_002a, IL_0059, IL_0060
            try
            {
                Socket socket = (Socket)_clients[clientKey];
                socket.SendFile(value);
                return true;
            }
            catch (Exception ex)
            {
                _log.Error($"服务端[SendFile]异常：{ex.Message}");
                return false;
            }
        }
        #endregion

    }
}
